home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
MPW_TOOL
/
TOOLS
/
TOOLS_WI
/
ICON_8
/
ICONX_FO
/
FSTRANL.C
< prev
next >
Wrap
Text File
|
1990-03-02
|
11KB
|
469 lines
/*
* File: fstranl.c
* Contents: any, bal, find, many, match, upto
*/
#include "::h:config.h"
#include "::h:rt.h"
#include "rproto.h"
#ifdef PreProcess
/* include(../M4/fncs.m4) /* */
/* */
#endif /* PreProcess */
/*
* any(c,s,i,j) - test if first character of s[i:j] is in c.
*/
FncDcl(any,4)
{
register word i, j;
long l1, l2;
int *cs, csbuf[CsetSize];
char sbuf[MaxCvtLen];
/*
* Arg1 must be a cset. Arg2 defaults to &subject; Arg3 defaults to &pos
* if Arg2 defaulted, 1 otherwise. Arg4 defaults to 0.
*/
if (cvcset(&Arg1, &cs, csbuf) == CvtFail)
RunErr(104, &Arg1);
switch (defstr(&Arg2, sbuf, &k_subject)) {
case Error:
RunErr(0, NULL);
case Defaulted:
if (defint(&Arg3, &l1, k_pos) == Error)
RunErr(0, NULL);
break;
default:
if (defint(&Arg3, &l1, (word)1) == Error)
RunErr(0, NULL);
}
if (defint(&Arg4, &l2, (word)0) == Error)
RunErr(0, NULL);
/*
* Convert Arg3 and Arg4 to positions in Arg2. If Arg3 == Arg4 then the
* specified substring of Arg2 is empty and any fails. Otherwise make
* Arg3 the smaller of the two. (Arg4 is of no further use.)
*/
i = cvpos(l1, StrLen(Arg2));
if (i == CvtFail)
Fail;
j = cvpos(l2, StrLen(Arg2));
if (j == CvtFail)
Fail;
if (i == j)
Fail;
if (i > j)
i = j;
/*
* If Arg2[Arg3] is not in the cset Arg1, fail.
*/
j = (word)StrLoc(Arg2)[i-1];
if (!Testb(j, cs))
Fail;
/*
* Return pos(s[i+1]).
*/
Arg0.dword = D_Integer;
IntVal(Arg0) = i + 1;
Return;
}
/*
* bal(c1,c2,c3,s,i,j) - find end of a balanced substring of s[i:j].
* Generates successive positions.
*/
FncDcl(bal,6)
{
register word i, j;
register int cnt, c;
word t;
long l1, l2;
int *cs1, *cs2, *cs3;
int csbuf1[CsetSize], csbuf2[CsetSize], csbuf3[CsetSize];
char sbuf[MaxCvtLen];
static int lpar[CsetSize] = /* '(' */
#if !EBCDIC
cset_display(0, 0, 0400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
#else /* !EBCDIC */
cset_display(0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
#endif /* !EBCDIC */
static int rpar[CsetSize] = /* ')' */
#if !EBCDIC
cset_display(0, 0, 01000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
#else /* !EBCDIC */
cset_display(0, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
#endif /* !EBCDIC */
/*
* Arg1 defaults to &cset; Arg2 defaults to '('; Arg3 defaults to
* ')'; Arg4 to &subject; Arg5 to &pos if Arg4 defaulted, 1 otherwise;
* Arg6 defaults to 0.
*/
if ((defcset(&Arg1, &cs1, csbuf1, k_cset.bits) == Error) ||
(defcset(&Arg2, &cs2, csbuf2, lpar) == Error) ||
(defcset(&Arg3, &cs3, csbuf3, rpar) == Error))
RunErr(0, NULL);
switch (defstr(&Arg4, sbuf, &k_subject)) {
case Error:
RunErr(0, NULL);
case Defaulted:
if (defint(&Arg5, &l1, k_pos) == Error)
RunErr(0, NULL);
break;
default:
if (defint(&Arg5, &l1, (word)1) == Error)
RunErr(0, NULL);
}
if (defint(&Arg6, &l2, (word)0) == Error)
RunErr(0, NULL);
/*
* Convert Arg5 and Arg6 to positions in Arg4 and order them.
*/
i = cvpos(l1, StrLen(Arg4));
if (i == CvtFail)
Fail;
j = cvpos(l2, StrLen(Arg4));
if (j == CvtFail)
Fail;
if (i > j) {
t = i;
i = j;
j = t;
}
/*
* Loop through characters in Arg4[Arg5:Arg6]. When a character in Arg2 is
* found, increment cnt; when a character in Arg3 is found, decrement
* cnt. When cnt is 0 there have been an equal number of occurrences
* of characters in Arg2 and Arg3, i.e., the string to the left of
* i is balanced. If the string is balanced and the current character
* (Arg4[i]) is in Arg1, suspend with i. Note that if cnt drops below
* zero, bal fails.
*/
cnt = 0;
Arg0.dword = D_Integer;
while (i < j) {
c = StrLoc(Arg4)[i-1];
if (cnt == 0 && Testb(c, cs1)) {
IntVal(Arg0) = i;
Suspend;
}
if (Testb(c, cs2))
cnt++;
else if (Testb(c, cs3))
cnt--;
if (cnt < 0)
Fail;
i++;
}
/*
* Eventually fail.
*/
Fail;
}
/*
* find(s1,s2,i,j) - find string s1 in s2[i:j] and return position in
* s2 of beginning of s1.
* Generates successive positions.
*/
FncDcl(find,4)
{
register word l;
register char *s1, *s2;
word i, j, t;
long l1, l2;
char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];
/*
* Arg1 must be a string. Arg2 defaults to &subject; Arg3 defaults
* to &pos if Arg2 is defaulted, or to 1 otherwise; Arg4 defaults
* to 0.
*/
if (cvstr(&Arg1, sbuf1) == CvtFail)
RunErr(103, &Arg1);
switch (defstr(&Arg2, sbuf2, &k_subject)) {
case Error:
RunErr(0, NULL);
case Defaulted:
if (defint(&Arg3, &l1, k_pos) == Error)
RunErr(0, NULL);
break;
default:
if (defint(&Arg3, &l1, (word)1) == Error)
RunErr(0, NULL);
}
if (defint(&Arg4, &l2, (word)0)== Error)
RunErr(0, NULL);
/*
* Convert Arg3 and Arg4 to absolute positions in Arg2 and order them.
*/
i = cvpos(l1, StrLen(Arg2));
if (i == CvtFail)
Fail;
j = cvpos(l2, StrLen(Arg2));
if (j == CvtFail)
Fail;
if (i > j) {
t = i;
i = j;
j = t;
}
/*
* Loop through Arg2[i:j] trying to find Arg1 at each point, stopping
* when the remaining portion Arg2[i:j] is too short to contain Arg1.
*/
Arg0.dword = D_Integer;
while (i <= j - StrLen(Arg1)) {
s1 = StrLoc(Arg1);
s2 = StrLoc(Arg2) + i - 1;
l = StrLen(Arg1);
/*
* Compare strings on a byte-wise basis; if the end is reached
* before inequality is found, suspend with the position of the
* string.
*/
do {
if (l-- <= 0) {
IntVal(Arg0) = i;
Suspend;
break;
}
} while (*s1++ == *s2++);
i++;
}
Fail;
}
/*
* many(c,s,i,j) - find longest prefix of s[i:j] of characters in c.
*/
FncDcl(many,4)
{
register word i, j, t;
int *cs, csbuf[CsetSize];
long l1, l2;
char sbuf[MaxCvtLen];
/*
* Arg1 must be a cset. Arg2 defaults to &subject; Arg3 defaults to
* &pos if Arg2 defaulted, 1 otherwise; Arg4 defaults to 0.
*/
if (cvcset(&Arg1, &cs, csbuf) == CvtFail)
RunErr(104, &Arg1);
switch (defstr(&Arg2, sbuf, &k_subject)) {
case Error:
RunErr(0, NULL);
case Defaulted:
if (defint(&Arg3, &l1, k_pos) == Error)
RunErr(0, NULL);
break;
default:
if (defint(&Arg3, &l1, (word)1) == Error)
RunErr(0, NULL);
}
if (defint(&Arg4, &l2, (word)0) == Error)
RunErr(0, NULL);
/*
* Convert Arg3 and Arg4 to absolute positions and order them.
*/
i = cvpos(l1, StrLen(Arg2));
if (i == CvtFail)
Fail;
j = cvpos(l2, StrLen(Arg2));
if (j == CvtFail)
Fail;
if (i == j)
Fail;
if (i > j) {
t = i;
i = j;
j = t;
}
/*
* Fail if first character of Arg2[i:j] is not in Arg1.
*/
t = (word)StrLoc(Arg2)[i-1];
if (!Testb(t, cs))
Fail;
/*
* Move i along Arg2[i:j] until a character that is not in Arg1 is found or
* the end of the string is reached.
*/
i++;
while (i < j) {
t = (word)StrLoc(Arg2)[i-1];
if (!Testb(t, cs))
break;
i++;
}
/*
* Return the position of the first character not in Arg1.
*/
Arg0.dword = D_Integer;
IntVal(Arg0) = i;
Return;
}
/*
* match(s1,s2,i,j) - test if s1 is prefix of s2[i:j].
*/
FncDcl(match,4)
{
register word i;
register char *s1, *s2;
word j, t;
long l1, l2;
char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];
/*
* Arg1 must be a string. Arg2 defaults to &subject; Arg3 defaults
* to &pos if Arg2 defaulted, 1 otherwise; Arg4 defaults to 0.
*/
if (cvstr(&Arg1, sbuf1) == CvtFail)
RunErr(103, &Arg1);
switch (defstr(&Arg2, sbuf2, &k_subject)) {
case Error:
RunErr(0, NULL);
case Defaulted:
if (defint(&Arg3, &l1, k_pos) == Error)
RunErr(0, NULL);
break;
default:
if (defint(&Arg3, &l1, (word)1) == Error)
RunErr(0, NULL);
}
if (defint(&Arg4, &l2, (word)0) == Error)
RunErr(0, NULL);
/*
* Convert Arg3 and Arg4 to absolute positions and order them.
*/
i = cvpos(l1, StrLen(Arg2));
if (i == CvtFail)
Fail;
j = cvpos(l2, StrLen(Arg2));
if (j == CvtFail)
Fail;
if (i > j) {
t = i;
i = j;
j = t - j;
}
else
j = j - i;
/*
* Cannot match unless Arg1 is as long as Arg2[i:j].
*/
if (j < StrLen(Arg1))
Fail;
/*
* Compare Arg1 with Arg2[i:j] for *Arg1 characters; fail if an inequality
* if found.
*/
s1 = StrLoc(Arg1);
s2 = StrLoc(Arg2) + i - 1;
for (j = StrLen(Arg1); j > 0; j--)
if (*s1++ != *s2++)
Fail;
/*
* Return position of end of matched string in Arg2.
*/
Arg0.dword = D_Integer;
IntVal(Arg0) = i + StrLen(Arg1);
Return;
}
/*
* upto(c,s,i,j) - find each occurrence in s[i:j] of a character in c.
* Generates successive positions.
*/
FncDcl(upto,4)
{
register word i, j, t;
long l1, l2;
int *cs, csbuf[CsetSize];
char sbuf[MaxCvtLen];
/*
* Arg1 must be a cset. Arg2 defaults to &subject; Arg3 defaults
* to &pos if Arg2 defaulted, 1 otherwise; Arg4 defaults to 0.
*/
if (cvcset(&Arg1, &cs, csbuf) == CvtFail)
RunErr(104, &Arg1);
switch (defstr(&Arg2, sbuf, &k_subject)) {
case Error:
RunErr(0, NULL);
case Defaulted:
if (defint(&Arg3, &l1, k_pos) == Error)
RunErr(0, NULL);
break;
default:
if (defint(&Arg3, &l1, (word)1) == Error)
RunErr(0, NULL);
}
if (defint(&Arg4, &l2, (word)0) == Error)
RunErr(0, NULL);
/*
* Convert Arg3 and Arg4 to positions in Arg2 and order them.
*/
i = cvpos(l1, StrLen(Arg2));
if (i == CvtFail)
Fail;
j = cvpos(l2, StrLen(Arg2));
if (j == CvtFail)
Fail;
if (i > j) {
t = i;
i = j;
j = t;
}
/*
* Look through Arg2[i:j] and suspend position of each occurrence of
* of a character in Arg1.
*/
while (i < j) {
t = (word)StrLoc(Arg2)[i-1];
if (Testb(t, cs)) {
Arg0.dword = D_Integer;
IntVal(Arg0) = i;
Suspend;
}
i++;
}
/*
* Eventually fail.
*/
Fail;
}